#include <gtest/gtest.h>
#include "gmock/gmock.h"

#include "../src/trophy.hpp"
#include "../src/player.hpp"
#include "../src/datatable.hpp"
#include "../src/dbmemory.hpp"


template<typename T, size_t size>
::testing::AssertionResult ArraysMatch(const T(&expected)[size], const T(&actual)[size]) {
	for(size_t i(0); i < size; ++i) {
		if(expected[i] != actual[i]) {
			return ::testing::AssertionFailure() << "array[" << i
			       << "] (" << actual[i] << ") != expected[" << i
			       << "] (" << expected[i] << ")";
		}
	}

	return ::testing::AssertionSuccess();
}

class TestTrophy : public ::testing::Test {
protected:
	void SetUp() override {
		Player::importData("test.txt", &data);
	}

	void TearDown() override {

	}

	PlayerData data;
};

TEST_F(TestTrophy, levelFromPower) {
	ASSERT_EQ(Trophy::levelFromPower(30199), 78);
	ASSERT_EQ(Trophy::levelFromPower(1678), 19);
	ASSERT_EQ(Trophy::levelFromPower(1829), 19);
	ASSERT_EQ(Trophy::levelFromPower(1830), 20);
	ASSERT_EQ(Trophy::levelFromPower(29303), 77);
}

TEST_F(TestTrophy, levelFromResource) {
	ASSERT_EQ(Trophy::levelFromResource(4144150), 456);
	ASSERT_EQ(Trophy::levelFromResource(1678667), 290);
	ASSERT_EQ(Trophy::levelFromResource(2514949), 355);

	ASSERT_EQ(Trophy::levelFromResource(2436949), 350);
	ASSERT_EQ(Trophy::levelFromResource(4014150), 449);
	ASSERT_EQ(Trophy::levelFromResource(1626667), 286);
}

TEST_F(TestTrophy, search) {
	DBMemory db(10);
	Trophy::variants(&db, &data);
	ASSERT_EQ(db.size(), 3);
	uint8_t p[2];
	uint8_t pe[3][2] = {{98, 100}, {99, 99}, {100, 98}};
	auto count = 0;

	while(db.get((char *)p, sizeof(p))) {
		ASSERT_TRUE(ArraysMatch(p, pe[count]));
		count++;
	}

	data.resBase.imatter = 1436949;
	Trophy::variants(&db, &data);
	ASSERT_EQ(db.size(), 8);

	for( auto i = 3000000; i < 5000000; i++){
		data.resBase.imatter = i;
		data.resBase.ultium = i;
		Trophy::variants(&db, &data);
		ASSERT_EQ(db.size(), 1);
	}
}

TEST_F(TestTrophy, pointsFromData) {
	ASSERT_EQ(Trophy::pointsBase(&data), 48215);
	ASSERT_EQ(Trophy::pointsTest(&data), 49440);
	ASSERT_EQ(Trophy::pointsTest(&data, true), 49784);

	data.resBase.imatter = 1436949;
	ASSERT_EQ(Trophy::pointsBase(&data), 45668);
	ASSERT_EQ(Trophy::pointsTest(&data), 46908);
	ASSERT_EQ(Trophy::pointsTest(&data, true), 47252);

	data.resBase.pcore = 40000;
	ASSERT_EQ(Trophy::pointsBase(&data), 35488);
	ASSERT_EQ(Trophy::pointsTest(&data, true), 37106);
}

TEST_F(TestTrophy, maxLevel) {
	for(auto i = 0; i < 90000; ++i) {
		for(auto j = 0; j < trophy ; ++j) {
			if(DataTable::trophyPriceTotal[j] > i) {
				ASSERT_EQ(j - 1, Trophy::maxLevel(i));
				break;
			}
		}
	}
}
